package Pages;

import clientMain.*;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.SortedMap;
import java.util.TreeMap;

import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;

/**
 * Sell Item Page
 * @author Andrew Fox
 *
 */

public class SellItemPage extends Page {
	TreeMap<Double,StringBuffer> nextPageProbabilities=new TreeMap<Double,StringBuffer>();
	double startPrice=0;
	double reservePrice=0;
	double buyNowPrice=0;
	Calendar sellTime=Calendar.getInstance();

	HashMap<String,StringBuffer>data=new HashMap<String,StringBuffer>();

	public SellItemPage(Page page){
		//		super(page.url,page.lastURL,page.client);
		//		this.html=page.html;
		//		this.pageType=page.pageType;
		super(page.url,page.html,page.client,page.pageType);
		this.pageOpenTime=page.pageOpenTime;
		this.lastURL=page.lastURL;
		if(HTML4)
			data=getFormData();
	}

	/**
	 * Determines the next link to go to in the application
	 * @return the URL or HTML of the next link, depending on whether
	 * 		   the previous entry contained a form or not
	 */
	public StringBuffer makeDecision() throws Exception{
		StringBuffer nextPage=new StringBuffer();
		StringBuffer nextLink=new StringBuffer();

		boolean sellitem=false;

		updateProbabilities();

		if(HTML4==false){
			ObjectMapper mapper = new ObjectMapper();
			if(verbose)System.out.println(html);
			if(html.indexOf("Apache Tomcat/7.0.11 - Error report")==-1){
				JsonNode node = mapper.readValue(html.toString(), JsonNode.class);
				sellitem=node.get("userID").getBooleanValue();
			}
		}

		nextLink=getRandomStringFromDist(nextPageProbabilities);

		if (nextLink.toString().equals("Sell")){
			StringBuffer auctionType=getRandomStringFromDist(clientGenerator.auctionType);

			SimpleDateFormat obDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			double sellDateProb=Math.random();
			if (sellDateProb<0.25)
				sellTime.add(Calendar.DAY_OF_YEAR,1);
			else if(sellDateProb<0.5)
				sellTime.add(Calendar.DAY_OF_YEAR,3);
			else if(sellDateProb<0.75)
				sellTime.add(Calendar.DAY_OF_YEAR,7);
			else 
				sellTime.add(Calendar.DAY_OF_YEAR,14);


			int numWords=getRandomIntFromDist(clientGenerator.titleTotalWords);;


			StringBuffer itemTitle=new StringBuffer();
			for (int i=0;i<numWords;i++){
				itemTitle.append(getRandomStringFromDist(clientGenerator.titleWords));
				if (i!=numWords-1)
					itemTitle.append(" ");
			}
			System.out.println("Item Title: "+itemTitle);
			if (auctionType.equals("auction")){
				this.startPrice=getRandomDoubleFromDist(clientGenerator.startingBid);
				if(Math.random()>0.5)
					this.reservePrice=1.1*this.startPrice;
			}
			else if(auctionType.equals("buyNow")){
				this.buyNowPrice=getRandomDoubleFromDist(clientGenerator.buyNowPrice);
			}
			else{
				this.startPrice=getRandomDoubleFromDist(clientGenerator.startingBid);
				if(Math.random()>0.5)
					this.reservePrice=1.1*this.startPrice;

				TreeMap<Double,Double>buyNowOptions=fixMapProbs(clientGenerator.buyNowPriceReverse.tailMap(this.startPrice));
				this.buyNowPrice=getRandomDoubleFromDist(buyNowOptions);
			}

			//	int numDescriptionCategories=getRandomIntFromDist(clientGenerator.itemSpecificsCat);
			int numWordsDescription=getRandomIntFromDist(clientGenerator.itemSpecificsDesc);
			StringBuffer itemSpecifics=new StringBuffer();
			for (int i=0;i<numWordsDescription;i++){
				itemSpecifics.append(getRandomStringFromDist(clientGenerator.itemSpecificsDescWords));
				if (i!=numWords-1)
					itemSpecifics.append(" ");
			}


			data.put("name", itemTitle);
			data.put("description", itemSpecifics);
			data.put("startPrice", new StringBuffer(Double.toString(startPrice)));
			data.put("reservePrice", new StringBuffer(Double.toString(reservePrice)));
			data.put("buyNowPrice", new StringBuffer(Double.toString(buyNowPrice)));
			data.put("categoryID", new StringBuffer("1"));
			data.put("quantity", new StringBuffer("1"));
			data.put("endDate",new StringBuffer(obDateFormat.format(sellTime.getTime())));
			System.out.println("SELLDATA "+data);
			// Think Time
			try{Thread.sleep(getThinkTime(nextLink.toString()));}
			catch(InterruptedException e){
				e.printStackTrace();
			}
		}
		if(HTML4){
			nextPage=doSubmit3(new StringBuffer(runSettings.rootURL).append("/sellitem?"),data,client);
		}
		else{
			if (sellitem==false){
				data.put("userID", client.userInfo.userID);
				nextPage=new StringBuffer(runSettings.rootURL).append("/sellitem?").append(createURL(data));
			}
			else{
				nextPage=new StringBuffer(runSettings.rootURL).append("/myaccount");
			}
		}
		if(verbose)System.out.println(nextPage);
		return nextPage;
	}


	/**
	 * Updates the probabilities of which page to transition to
	 */
	public void updateProbabilities(){
		double probSum=1;
		double homeProb=0;
		double searchProb=0;
		double myAccountProb=0;
		double sellProb=1;
		double browseProb=0;
		double logOutProb=0;

		nextPageProbabilities.put(probSum,new StringBuffer("Home"));
		probSum-=homeProb;
		nextPageProbabilities.put(probSum,new StringBuffer("search"));
		probSum-=searchProb;
		nextPageProbabilities.put(probSum,new StringBuffer("My Account"));
		probSum-=myAccountProb;
		nextPageProbabilities.put(probSum,new StringBuffer("Sell"));
		probSum-=sellProb;
		nextPageProbabilities.put(probSum,new StringBuffer("Browse"));
		probSum-=browseProb;
		nextPageProbabilities.put(probSum,new StringBuffer("Log out"));

	}

	/**
	 * Determines the think time before going to the next page
	 * Deducts from the think time the amount of time since the 
	 * page opened until this calculation is performed
	 * @return Think time in ms
	 */
	public int getThinkTime(String nextMove){
		int thinkTime=(int)expDist(initialThinkTime);
		if (nextMove=="Sell"){
			thinkTime+=(int)((data.get("name").length()+data.get("description").length()+Double.toString(startPrice).length()+Double.toString(reservePrice).length()+Double.toString(buyNowPrice).length()+data.get("endDate").length())/client.typingSpeed);
		}
		if (verbose)System.out.println("User: "+client.userInfo.username+" - Think Time: "+thinkTime+" ms");
		return (int) ((thinkTime-(new Date().getTime()-pageOpenTime))/runSettings.thinkTimeSpeedUpFactor);
	}

	/**
	 * Recalculates probabilities of a truncated distribution to
	 * normalize all probabilities
	 * @param map1
	 * @return
	 */
	public TreeMap<Double,Double> fixMapProbs(SortedMap <Double,Double> map1){
		TreeMap<Double,Double> map2 = new TreeMap<Double,Double>();
		double lastValue=map1.get(map1.lastKey());
		for (double m:map1.keySet()){
			map2.put((map1.get(m)-lastValue)/(1-lastValue), m);
		}

		return map2;
	}


}